home *** CD-ROM | disk | FTP | other *** search
/ SGI Hot Mix 17 / Hot Mix 17.iso / HM17_SGI / research / examples / demo / demosrc / d_orbit.pro < prev    next >
Text File  |  1997-07-08  |  38KB  |  1,143 lines

  1. ; $Id: d_orbit.pro,v 1.19 1997/04/23 02:03:20 tremblay Exp $
  2. ;
  3. ;  Copyright (c) 1997, Research Systems, Inc. All rights reserved.
  4. ;       Unauthorized reproduction prohibited.
  5. ;
  6. ;+
  7. ;  FILE:
  8. ;       d_orbit.pro
  9. ;
  10. ;  CALLING SEQUENCE: d_orbit
  11. ;
  12. ;  PURPOSE:
  13. ;       Shows an orbiting satellite. The forcings are the Earth's
  14. ;       central body and J2.
  15. ;
  16. ;  MAJOR TOPICS: Visualization.
  17. ;
  18. ;  CATEGORY:
  19. ;       IDL 5.0
  20. ;
  21. ;  INTERNAL FUNCTIONS and PROCEDURES:
  22. ;       fun getRotation         - Rotation values of the satellite
  23. ;       fun createSatellite     - create the satellite object
  24. ;       fun findE               - Compute the eccentric anomaly
  25. ;       fun findPosition        - Compute the satelitte's ephemeris.
  26. ;       pro d_orbit_Event         - Event handler
  27. ;       pro d_orbit_Cleanup       - Cleanup
  28. ;       pro d_orbit               - Main procedure
  29. ;
  30. ;  EXTERNAL FUNCTIONS, PROCEDURES, and FILES:
  31. ;       pro orb__define.pro     - Create an orb object
  32. ;       pro trackball__define   - Create the trackball object
  33. ;       pro gettips             - Get the tip text structure.
  34. ;       pro widtips             - Create the widget text for tips.
  35. ;       pro sizetips            - Size the widget text for tips.
  36. ;       orbit.txt
  37. ;       orbit.tip
  38. ;
  39. ;  REFERENCE: 1) Fundamentals of celestial mechanics (2nd ed.)
  40. ;                J.M.A. Danby
  41. ;                Willmann-Bell editor
  42. ;                ISBN 0-943396-20-4
  43. ;             2) Methods of orbit determination
  44. ;                P. R. Escobal
  45. ;                R. E. Kreiger publishing company
  46. ;                ISBN 0-88275-319-3
  47. ;
  48. ;  NAMED STRUCTURES:
  49. ;       none.
  50. ;
  51. ;  COMMON BLOCS:
  52. ;       none.
  53. ;
  54. ;  MODIFICATION HISTORY: Written by DAT,RSI,  July 1996 
  55. ;
  56. ;-
  57. ;---------------------------------------------------------------------------
  58. ;
  59. ;  Purpose:  Returns  3 rotation angle increment in degrees
  60. ;
  61. ;
  62. function GetRotation, $
  63.     time         ; IN: time in sec passed the epoch
  64.  
  65.     angles = FLTARR(3)
  66.     xAngle = 1.0d-3 * time
  67.     yAngle = 4.0d-2 * time
  68.     zAngle = 3.4d-3 * time
  69.  
  70.     angles = [ xAngle, yAngle, zAngle]
  71.  
  72.     RETURN, angles
  73.  
  74. end
  75.  
  76. ;---------------------------------------------------------------------------
  77. ;
  78. ;  Purpose:  Create a satellite object and return it into a model
  79. ;
  80. ;
  81. function CreateSatellite
  82.  
  83.     mainModel = OBJ_NEW('IDLgrModel')
  84.  
  85.     ;  Create bloc1 : main satellite body in yellow.
  86.     ;
  87.     xp=[-0.07, 0.07, 0.07,-0.07, $
  88.         -0.07, 0.07, 0.07,-0.07]
  89.     yp=[-0.40,-0.40, 0.40, 0.40, $
  90.         -0.40,-0.40, 0.40, 0.40]
  91.     zp=[ 0.07, 0.07, 0.07, 0.07, $
  92.         -0.07,-0.07,-0.07,-0.07]
  93.     bloc1Vertices = fltarr(3,8)
  94.     bloc1Vertices = [ [xp], [yp], [zp] ]
  95.     bloc1Vertices = TRANSPOSE(bloc1Vertices)
  96.     bloc1Mesh = [ [4,0,1,2,3], $
  97.                   [4,1,5,6,2], $
  98.                   [4,4,7,6,5], $
  99.                   [4,0,3,7,4], $
  100.                   [4,3,2,6,7], $
  101.                   [4,0,4,5,1] ]
  102.     bloc1List = FLTARR(3,24)
  103.     bloc1NewMesh = bloc1Mesh
  104.     j = 0
  105.     for i = 0, 5 do begin
  106.         bloc1List(0:2, i*4+0) = bloc1Vertices(0:2, bloc1Mesh(i*5+1))
  107.         bloc1List(0:2, i*4+1) = bloc1Vertices(0:2, bloc1Mesh(i*5+2))
  108.         bloc1List(0:2, i*4+2) = bloc1Vertices(0:2, bloc1Mesh(i*5+3))
  109.         bloc1List(0:2, i*4+3) = bloc1Vertices(0:2, bloc1Mesh(i*5+4))
  110.         bloc1NewMesh(*,i) = [4, j+0, j+1, j+2, j+3]
  111.         j = j + 4
  112.     endfor
  113.     oBloc1 = OBJ_NEW('IDLgrPolygon', bloc1List, $
  114.         POLYGONS=bloc1NewMesh, COLOR=[255,255,0] )
  115.     mainModel->Add, oBloc1
  116.  
  117.     ;  Create bloc2 : solar array panel.
  118.     ;
  119.     xp=[0.20, 0.60, 0.60, 0.20, $
  120.         0.20, 0.60, 0.60, 0.20]
  121.     yp=[-0.20,-0.20, 0.20, 0.20, $
  122.         -0.20,-0.20, 0.20, 0.20]
  123.     zp=[ 0.02, 0.02, 0.02, 0.02, $
  124.         -0.02,-0.02,-0.02,-0.02]
  125.     bloc2Vertices = fltarr(3,8)
  126.     bloc2Vertices = [ [xp], [yp], [zp] ]
  127.     bloc2Vertices = TRANSPOSE(bloc2Vertices)
  128.     bloc2Mesh = [ [4,0,1,2,3], $
  129.                   [4,1,5,6,2], $
  130.                   [4,4,7,6,5], $
  131.                   [4,0,3,7,4], $
  132.                   [4,3,2,6,7], $
  133.                   [4,0,4,5,1] ]
  134.     bloc2List = FLTARR(3,24)
  135.     bloc2NewMesh = bloc1Mesh
  136.     j = 0
  137.     for i = 0, 5 do begin
  138.         bloc2List(0:2, i*4+0) = bloc2Vertices(0:2, bloc2Mesh(i*5+1))
  139.         bloc2List(0:2, i*4+1) = bloc2Vertices(0:2, bloc2Mesh(i*5+2))
  140.         bloc2List(0:2, i*4+2) = bloc2Vertices(0:2, bloc2Mesh(i*5+3))
  141.         bloc2List(0:2, i*4+3) = bloc2Vertices(0:2, bloc2Mesh(i*5+4))
  142.         bloc2NewMesh(*,i) = [4, j+0, j+1, j+2, j+3]
  143.         j = j + 4
  144.     endfor
  145.     oBloc2 = OBJ_NEW('IDLgrPolygon', bloc2List, $
  146.         POLYGONS=bloc2NewMesh, COLOR=[100,100,255] )
  147.     mainModel->Add, oBloc2
  148.  
  149.     ;  Create bloc3 : the other solar array panel.
  150.     ;
  151.     xp=[-0.20, -0.60, -0.60, -0.20, $
  152.         -0.20, -0.60, -0.60, -0.20]
  153.     yp=[-0.20,-0.20, 0.20, 0.20, $
  154.         -0.20,-0.20, 0.20, 0.20]
  155.     zp=[ 0.02, 0.02, 0.02, 0.02, $
  156.         -0.02,-0.02,-0.02,-0.02]
  157.     bloc3Vertices = fltarr(3,8)
  158.     bloc3Vertices = [ [xp], [yp], [zp] ]
  159.     bloc3Vertices = TRANSPOSE(bloc3Vertices)
  160.     bloc3Mesh = [ [4,0,1,2,3], $
  161.                   [4,1,5,6,2], $
  162.                   [4,4,7,6,5], $
  163.                   [4,0,3,7,4], $
  164.                   [4,3,2,6,7], $
  165.                   [4,0,4,5,1] ]
  166.     bloc3List = FLTARR(3,24)
  167.     bloc3NewMesh = bloc3Mesh
  168.     j = 0
  169.     for i = 0, 5 do begin
  170.         bloc3List(0:2, i*4+0) = bloc3Vertices(0:2, bloc3Mesh(i*5+1))
  171.         bloc3List(0:2, i*4+1) = bloc3Vertices(0:2, bloc3Mesh(i*5+2))
  172.         bloc3List(0:2, i*4+2) = bloc3Vertices(0:2, bloc3Mesh(i*5+3))
  173.         bloc3List(0:2, i*4+3) = bloc3Vertices(0:2, bloc3Mesh(i*5+4))
  174.         bloc3NewMesh(*,i) = [4, j+0, j+1, j+2, j+3]
  175.         j = j + 4
  176.     endfor
  177.     oBloc3 = OBJ_NEW('IDLgrPolygon', bloc3List, $
  178.         POLYGONS=bloc3NewMesh, COLOR=[100,100,255] )
  179.     mainModel->Add, oBloc3
  180.  
  181.     ;  Create the 4 white line connecting the main satellite
  182.     ;  body to the solar array panels.
  183.     ;
  184.     x = [0.07, 0.20]
  185.     y = [0.00, 0.18]
  186.     z = [0.0, 0.0]
  187.     oLine1 = OBJ_NEW('IDLgrPolyline', x, y, z, $
  188.         COLOR=[255, 255, 255])
  189.     mainModel->Add, oLine1
  190.  
  191.     x = [0.07, 0.20]
  192.     y = [-0.00, -0.18]
  193.     z = [0.0, 0.0]
  194.     oLine2 = OBJ_NEW('IDLgrPolyline', x, y, z, $
  195.         COLOR=[255, 255, 255])
  196.     mainModel->Add, oLine2
  197.  
  198.     x = [-0.07, -0.20]
  199.     y = [0.00, 0.18]
  200.     z = [0.0, 0.0]
  201.     oLine3 = OBJ_NEW('IDLgrPolyline', x, y, z, $
  202.         COLOR=[255, 255, 255])
  203.     mainModel->Add, oLine3
  204.  
  205.     x = [-0.07, -0.20]
  206.     y = [-0.00, -0.18]
  207.     z = [0.0, 0.0]
  208.     oLine4 = OBJ_NEW('IDLgrPolyline', x, y, z, $
  209.         COLOR=[255, 255, 255])
  210.     mainModel->Add, oLine4
  211.  
  212.     mainModel->Scale, 0.5, 0.5, 0.5
  213.  
  214.     RETURN, mainModel
  215.  
  216. end
  217.  
  218. ;--------------------------------------------------------------------------
  219. ;
  220. ;  Purpose:  Find the eccentric anomaly
  221. ;
  222. function findE, $
  223.     e, $        ; IN:  eccentricity (dimensionless)
  224.     M, $        ; IN:  Mean anomaly
  225.     tolerance   ; tolerance of iterative process
  226.  
  227.     M = M MOD (2.0*!DPI)
  228.     diffx = 2.0 * tolerance
  229.     xold = M
  230.     while(diffx gt tolerance) do begin
  231.         fx = xold - e*sin(xold) - M
  232.         dfx = 1.0 - e*cos(xold)
  233.         xnew = xold - fx/dfx
  234.         diffx = xnew - xold
  235.         xold = xnew
  236.     endwhile
  237.     RETURN, xnew
  238. end
  239.  
  240. ;--------------------------------------------------------------------------
  241. ;
  242. ;  Purpose:  Function returns the satellite position in
  243. ;            the geocentric coordinates system given the
  244. ;            time (in seconds) passed the epoch.
  245. ;
  246. function FindPosition, $
  247.     sOrbit, $  ; IN:  structure containing the orbital elements
  248.     time       ; IN:  time in seconds passed the epoch
  249.  
  250.     rad = !DPI / 180.0
  251.     sini = sin(sOrbit.i * rad)
  252.     cosi = cos(sOrbit.i * rad)
  253.  
  254.     ;  Compute the 3 orbital elements affected by J2 and
  255.     ;  compute their new values.
  256.     ;
  257.     M = sOrbit.M0*rad + sOrbit.dMdt * time
  258.     omega = sOrbit.omega0*rad + sOrbit.dOmegadt * time
  259.     w = sOrbit.w0*rad + sOrbit.dwdt * time
  260.  
  261.     ;  Initialize the p and q vector for the
  262.     ;  transoformation matrix form the orbital plane to
  263.     ;  earth-fixed coordinate system of coordinates.
  264.     ;
  265.     p = FLTARR(3,3)
  266.     q = FLTARR(3)
  267.     cosOmega = cos(omega)
  268.     sinOmega = sin(omega)
  269.     cosw = cos(w)
  270.     sinw = sin(w)
  271.     p(0,0) = cosw*cosOmega - sinw*sinOmega*cosi
  272.     p(0,1) = cosw*sinOmega + sinw*cosOmega*cosi
  273.     p(0,2) = sinw*sini
  274.     p(1,0) = - sinw*cosOmega - cosw*sinOmega*cosi
  275.     p(1,1) = - sinw*sinOmega + cosw*cosOmega*cosi
  276.     p(1,2) = cosw*sini
  277.     p(2,0) = sinOmega*sini
  278.     p(2,1) = -cosOmega*sini
  279.     p(2,2) = cosi
  280.  
  281.     ;  Find the eccentric anomaly using the 'Newton' method.
  282.     ;
  283.     tolerance = 1.0d-5
  284.     EAnomaly = findE(sOrbit.e, M, tolerance)
  285.  
  286.     ;  Find the cartesian coordinates in the orbital plane.
  287.     ;
  288.     pp = FLTARR(3)
  289.     pp(0) = sOrbit.a*(cos(eAnomaly) - sOrbit.e)
  290.     pp(1) = sOrbit.a * SQRT(1.- sOrbit.e*sOrbit.e) * sin(eAnomaly)
  291.     pp(2) = 0.0
  292.  
  293.     ;  Find the satellite position in Earth fixed coordinate system
  294.     ;  Note : x axis points toward the  ernal equinox
  295.     ;         z axis points toward the Earth body-fixed z axis
  296.     ;         y axis is orthonormal to x and z
  297.     ;
  298.     xf = FLTARR(3)
  299.     xf = pp # p
  300.  
  301.     RETURN, xf
  302. end
  303.  
  304. ;--------------------------------------------------------------------------
  305. ;
  306. ;  Purpose:  Handle the events
  307. ;
  308. pro d_orbit_event, $
  309.      sEvent       ; IN:  event structure
  310.  
  311.     ;  Quit the application using the close box.
  312.     ;
  313.     if (TAG_NAMES(sEvent, /STRUCTURE_NAME) EQ $
  314.         'WIDGET_KILL_REQUEST') then begin
  315.         WIDGET_CONTROL, sEvent.top, /DESTROY
  316.         RETURN
  317.     endif
  318.  
  319.     WIDGET_CONTROL, sEvent.id, GET_UVALUE=uValue
  320.  
  321.     case uValue of
  322.         ;  Start the animation.
  323.         ;
  324.         'START' : begin
  325.             WIDGET_CONTROL, sEvent.top, GET_UVALUE=sState, /NO_COPY
  326.             WIDGET_CONTROL, sState.wRightBase, TIMER=sState.timer
  327.             sState.stopFlag = 0
  328.             WIDGET_CONTROL, sState.wStopButton, SENSITIVE=1
  329.             WIDGET_CONTROL, sState.wResetButton, SENSITIVE=0
  330.             WIDGET_CONTROL, sState.wStartButton, SENSITIVE=0
  331.             WIDGET_CONTROL, sEvent.top, SET_UVALUE=sState, /NO_COPY
  332.         end
  333.  
  334.         ;  Handle the widget timer event. This event create another
  335.         ;  widget timer event, hence creating a loop. The loop is
  336.         ;  broken by pushing the 'STOP' button.
  337.         ;
  338.         'TIMER' : begin
  339.  
  340.             WIDGET_CONTROL, sEvent.top, GET_UVALUE=sState, /NO_COPY
  341.  
  342.             ;  Reset if time greater than 1 d7 seconds (115 days).
  343.             ;
  344.             if (sState.time GT 1.0d7) then begin
  345.                 WIDGET_CONTROL, sEvent.top, GET_UVALUE=sState, /NO_COPY
  346.                 WIDGET_CONTROL, sState.wStopButton, SENSITIVE=0
  347.                 WIDGET_CONTROL, sState.wResetButton, SENSITIVE=0
  348.                 WIDGET_CONTROL, sState.wStartButton, SENSITIVE=1
  349.                 sState.oEarthRotationModel->SetProperty, $
  350.                     TRANSFORM=sState.initEarthTM
  351.                 sState.oSatRotationModel->SetProperty, $
  352.                     TRANSFORM=sState.initSatTM
  353.                 sState.oTopModel->SetProperty, $
  354.                     TRANSFORM=sState.initTopTM
  355.                 sState.oSky->Rotate,[0,0,1], -sState.skyAngle
  356.                 delta = sState.initSatPosition-sState.Position
  357.                 sState.oSatModel->Translate, delta(1), delta(2), delta(0)
  358.                 sState.oWindow->draw, sState.oView
  359.                 sState.time = 0.0
  360.                 sState.position = sState.initSatPosition
  361.                 WIDGET_CONTROL, sEvent.top, SET_UVALUE=sState, /NO_COPY
  362.                 RETURN
  363.             endif
  364.  
  365.             ;  Process the animation only if the 'STOP' button has
  366.             ;  not been pushed.
  367.             ;
  368.             if (sState.stopFlag EQ 0) then begin
  369.  
  370.                 ;  Increment the time.
  371.                 ;
  372.                 sState.time = sState.time + sState.timeIncrement
  373.  
  374.                 ;  Given the time (in sec.) passed the epoch, compute
  375.                 ;  The satellite ephemeris (x, y, z, position).
  376.                 ;
  377.                 newPosition = FindPosition(sState.sOrbit, sState.time)
  378.                 newPosition = newPosition/6378137.0
  379.                 delta = newPosition - sState.position
  380.                 sState.Position = newPosition
  381.  
  382.  
  383.                 ;  Translate the satellite.
  384.                 ;  Notice the axis correspondance :
  385.                 ;  orbit coord. system          graphic cood. system
  386.                 ;
  387.                 ;          x                              z
  388.                 ;          y                              x
  389.                 ;          z                              y
  390.                 ;  In order to make this transofrmation, the translation
  391.                 ;  is done as follows :
  392.                 ;
  393.                 sState.oSatModel->Translate, delta(1), delta(2), delta(0)
  394.  
  395.                 ;  Rotate the satellite.
  396.                 ;
  397.                 angles = GetRotation(sState.timeIncrement)
  398.                 sState.oSatRotationModel->Rotate, [1,0,0], angles(0)
  399.                 sState.oSatRotationModel->Rotate, [0,1,0], angles(1)
  400.                 sState.oSatRotationModel->Rotate, [0,0,1], angles(2)
  401.  
  402.                 ;  Rotate the earth and keep track of the sky rotation
  403.                 ;
  404.                 earthRotationRate = 0.004178074   ; degrees per sec
  405.                 earthAngle = earthRotationRate*sState.timeIncrement
  406.                 sState.oEarthRotationModel->Rotate, [0,1,0], earthAngle
  407.                 sState.oSky->Rotate,[0,0,1], -earthAngle*1.5
  408.                 sState.skyAngle = sState.skyAngle - (earthAngle*1.5)
  409.                 sState.skyAngle = (sState.skyAngle MOD 360)
  410.  
  411.                 ;  Draw the new frame.
  412.                 ;
  413.                 sState.oWindow->Draw, sState.oView
  414.  
  415.                 ;  Create a timer event to form the animation loop
  416.                 ;
  417.                 WIDGET_CONTROL, sState.wRightBase, TIMER=sState.timer
  418.  
  419.             endif
  420.  
  421.             WIDGET_CONTROL, sEvent.top, SET_UVALUE=sState, /NO_COPY
  422.          end
  423.  
  424.         ;  Handle events of the drawing area.
  425.         ;
  426.         'DRAWING' : begin
  427.  
  428.             WIDGET_CONTROL, sEvent.top, GET_UVALUE=sState, /NO_COPY
  429.  
  430.             ;  Expose.
  431.             ;
  432.             if (sEvent.type EQ 4) then begin
  433.                 sState.oWindow->draw, sState.oView
  434.                 WIDGET_CONTROL, sEvent.top, SET_UVALUE=sState, /NO_COPY
  435.                 RETURN
  436.             endif
  437.  
  438.             ;  Handle trackball update.
  439.             ;
  440.             bHaveTransform = sState.oTrack->Update(sEvent, TRANSFORM=qmat )
  441.             if (bHaveTransform NE 0) then begin
  442.                 sState.oTopModel->GetProperty, TRANSFORM=t
  443.                 mt = t # qmat
  444.                 sState.oTopModel->SetProperty,TRANSFORM=mt
  445.             endif
  446.  
  447.             ;  Handle button press.
  448.             ;
  449.             if (sEvent.type EQ 0) then begin
  450.                 sState.btndown = 1b
  451.                 sState.oWindow->SetProperty, QUALITY=0
  452.                 WIDGET_CONTROL,sState.wDraw, /DRAW_MOTION
  453.             endif
  454.  
  455.             ;  Handle button motion.
  456.             ;
  457.             if (sEvent.type EQ 2) then begin
  458.                 if (bHaveTransform) then $
  459.                     sState.oWindow->Draw, sState.oView
  460.             endif
  461.  
  462.             ;  Handle button release
  463.             ;
  464.             if (sEvent.type EQ 1) then begin
  465.                 if (sState.btndown EQ 1b) then begin
  466.                     sState.oWindow->SetProperty, QUALITY=2
  467.                     sState.oWindow->Draw, sState.oview
  468.                 endif
  469.                 sState.btndown = 0b
  470.                 WIDGET_CONTROL, sState.wDraw, DRAW_MOTION=0
  471.             endif
  472.  
  473.             WIDGET_CONTROL, sEvent.top, SET_UVALUE=sState, /NO_COPY
  474.         end
  475.  
  476.         ;  Stop the animation.
  477.         ;
  478.         'STOP' : begin
  479.             WIDGET_CONTROL, sEvent.top, GET_UVALUE=sState, /NO_COPY
  480.             sState.stopFlag = 1
  481.             WIDGET_CONTROL, sState.wStopButton, SENSITIVE=0
  482.             WIDGET_CONTROL, sState.wResetButton, SENSITIVE=1
  483.             WIDGET_CONTROL, sState.wStartButton, SENSITIVE=1
  484.             WIDGET_CONTROL, sEvent.top, SET_UVALUE=sState, /NO_COPY
  485.             RETURN
  486.         end
  487.  
  488.         ;  Reset the initial state (time and orientation of the objects.)
  489.         ;
  490.         'RESET' : begin
  491.             WIDGET_CONTROL, sEvent.top, GET_UVALUE=sState, /NO_COPY
  492.             WIDGET_CONTROL, sState.wTopBase, SENSITIVE=0
  493.             WIDGET_CONTROL, sState.wStopButton, SENSITIVE=0
  494.             WIDGET_CONTROL, sState.wResetButton, SENSITIVE=0
  495.             WIDGET_CONTROL, sState.wStartButton, SENSITIVE=1
  496.             sState.oEarthRotationModel->SetProperty, $
  497.                 TRANSFORM=sState.initEarthTM
  498.             sState.oSatRotationModel->SetProperty, $
  499.                 TRANSFORM=sState.initSatTM
  500.             sState.oTopModel->SetProperty, $
  501.                 TRANSFORM=sState.initTopTM
  502.             sState.oSky->Rotate,[0,0,1], -sState.skyAngle
  503.             delta = sState.initSatPosition-sState.Position
  504.             sState.oSatModel->Translate, delta(1), delta(2), delta(0)
  505.             sState.oWindow->draw, sState.oView
  506.             sState.time = 0.0
  507.             sState.position = sState.initSatPosition
  508.             WIDGET_CONTROL, sState.wTopBase, SENSITIVE=1
  509.             WIDGET_CONTROL, sEvent.top, SET_UVALUE=sState, /NO_COPY
  510.             RETURN
  511.         end
  512.  
  513.         ;  Scale the satellite.
  514.         ;
  515.         'SCALING' : begin
  516.             WIDGET_CONTROL, sEvent.top, GET_UVALUE=sState, /NO_COPY
  517.             WIDGET_CONTROL, sState.wScalingSlider, GET_VALUE=scale
  518.  
  519.             scale = 0.75 + FLOAT(scale) / 100.0
  520.             scalep = scale*100.0
  521.             scalingString = STRING(scalep, FORMAT='(f5.1)') + ' %'
  522.             WIDGET_CONTROL, sState.wScalingLabel2, $
  523.                 SET_VALUE=scalingString
  524.  
  525.             transform = [[scale, 0, 0, 0.0], [0, scale, 0, 0.0], $
  526.             [0, 0, scale, 0.0], [0, 0, 0, 1]]
  527.             sState.oSatScalingModel->SetProperty, TRANSFORM=transform
  528.             WIDGET_CONTROL, sState.wTopBase, /HOURGLASS
  529.             sState.oWindow->Draw, sState.oView
  530.             WIDGET_CONTROL, sEvent.top, SET_UVALUE=sState, /NO_COPY
  531.         end
  532.  
  533.         ;  Determine the time step between each redraw.
  534.         ;  A larger time step will make the satellite to
  535.         ;  translate at a faster rate but the  animation
  536.         ;  will be less 'smoother'.
  537.         ;
  538.         'STEP' : begin
  539.             WIDGET_CONTROL, sEvent.top, GET_UVALUE=sState, /NO_COPY
  540.             WIDGET_CONTROL, sState.wStepSlider, GET_VALUE=timeIncrement
  541.             sState.timeIncrement = timeIncrement
  542.             WIDGET_CONTROL, sEvent.top, SET_UVALUE=sState, /NO_COPY
  543.         end
  544.  
  545.         ;  Display the information text file.
  546.         ;
  547.         'ABOUT' : BEGIN
  548.             ; Verify that there is only one instance of xdisplayfile
  549.             ;
  550.             if (Xregistered('XDisplayFile') NE 0) then RETURN
  551.             XDisplayFile, filepath("orbit.txt", $
  552.                 SUBDIR=['examples','demo','demotext']), $
  553.                 DONE_BUTTON='Done', $
  554.                 TITLE="About orbiting satellite", $
  555.                 GROUP=sEvent.top, WIDTH=55, HEIGHT=14
  556.         END   ; of ABOUT
  557.  
  558.         ;  Quit this application.
  559.         ;
  560.         'QUIT' : begin
  561.             WIDGET_CONTROL, sEvent.top, /DESTROY
  562.         end
  563.  
  564.         ELSE :   ;  do nothing
  565.  
  566.     endcase
  567. end
  568.  
  569. ;--------------------------------------------------------------------------
  570. ;
  571. ;  Purpose:  Destroy the top objects and restore the previous
  572. ;            color table
  573. ;
  574. pro D_Orbit_Cleanup, $
  575.     wTopBase        ;  IN: top level base identifier
  576.  
  577.     WIDGET_CONTROL, wTopBase, GET_UVALUE=sState, /NO_COPY
  578.  
  579.     ;  Destroy the top objects
  580.     ;
  581.     OBJ_DESTROY, sState.oView
  582.     OBJ_DESTROY, sState.oTrack
  583.     OBJ_DESTROY, sState.oText
  584.     OBJ_DESTROY, sState.oFont
  585.     OBJ_DESTROY, sState.oContainer
  586.  
  587.     ;  Restore the color table
  588.     ;
  589.     TVLCT, sState.colorTable
  590.  
  591.     if WIDGET_INFO(sState.groupBase, /VALID_ID) then $
  592.         WIDGET_CONTROL, sState.groupBase, /MAP
  593.  
  594. end   ;  of d_orbit_Cleanup
  595.  
  596. ;--------------------------------------------------------------------------
  597. ;
  598. ;  Purpose:  Show a satellite orbiting the Earth
  599. ;
  600. pro d_orbit, $
  601.     GROUP=group, $         ; IN: (opt) semi-major axis (meters)
  602.     AXIS=a, $              ; IN: (opt) semi-major axis (meters)
  603.     INCLINATION=i, $       ; IN: (opt) inclination (deg.)
  604.     ECCENTRICITY=e, $      ; IN: (opt) eccentricity
  605.     MEANANOMALY=M0, $      ; IN: (opt) mean anomaly (deg.)
  606.     NODE=omega0, $         ; IN: (opt) longitude of ascending node (deg.)
  607.     PERIGEE=w0, $          ; IN: (opt) argument of perigee (deg.)
  608.     SELECTION=select, $    ; IN: (opt) 1 = circular orbit
  609.                            ;           2 = elliptical orbit (default)
  610.                            ;           3 = polar orbit
  611.     APPTLB = appTLB        ; OUT: (opt) TLB of this application
  612.  
  613.  
  614.     ;  Check the validity of the group identifier.
  615.     ;
  616.     ngroup = N_ELEMENTS(group)
  617.     if (ngroup NE 0) then begin
  618.         check = WIDGET_INFO(group, /VALID_ID)
  619.         if (check NE 1) then begin
  620.             print,'Error, the group identifier is not valid'
  621.             print, 'Return to the main application'
  622.             RETURN
  623.         endif
  624.         groupBase = group
  625.     endif else groupBase = 0L
  626.  
  627.     ;  The default values of the orbital elements are those of
  628.     ;  the elliptical orbit
  629.     ;
  630.     ;  NOTE :  In this code, the value range of the orbital elements are :
  631.     ;
  632.     ;  a     :  9200 to 11000 km
  633.     ;  e     :  0  to 0.3
  634.     ;  i     :  0  to 180
  635.     ;  M     :  0 to 360
  636.     ;  omega :  0 to 360
  637.     ;  w     :  0 to 360
  638.     ;
  639.  
  640.     ;  Initialize the Keplerian orbit elements
  641.     ;  at the epoch time here
  642.     ;
  643.  
  644.     ;  Semi-major axis (in meters).
  645.     ;
  646.     if (N_ELEMENTS(a) NE 0) then begin
  647.         a = FLOAT(a)
  648.         if ( (a LT 9200000.0) OR (a GT 11000000.0) ) then $
  649.             a = 9200000.0d0
  650.     endif else begin
  651.         a = 9200000.0d0
  652.     endelse
  653.  
  654.     ;  Eccentricity (dimensionless).
  655.     ;
  656.     if (N_ELEMENTS(e) NE 0) then begin
  657.         e = FLOAT(e)
  658.         if ( (e LT 0.0) OR (e GT 0.3) ) then $
  659.             e = 0.3
  660.     endif else begin
  661.         e = 0.3
  662.     endelse
  663.  
  664.     ;  Inclination (in degrees).
  665.     ;
  666.     if (N_ELEMENTS(i) NE 0) then begin
  667.         i = FLOAT(i)
  668.         if ( (i LT 0.0) OR (i GT 180.0) ) then $
  669.             i = 75.0
  670.     endif else begin
  671.         i = 75.0
  672.     endelse
  673.  
  674.     ;  Mean anomaly (in degrees).
  675.     ;
  676.     if (N_ELEMENTS(M0) NE 0) then begin
  677.         M0 = FLOAT(M0)
  678.         if ( (M0 LT 0.0) OR (M0 GT 360.0) ) then $
  679.             M0 = 38.0
  680.     endif else begin
  681.         M0 = 38.0
  682.     endelse
  683.  
  684.     ;  Longitude of ascending node (in degrees).
  685.     ;
  686.     if (N_ELEMENTS(omega0) NE 0) then begin
  687.         omega0 = FLOAT(omega0)
  688.         if ( (omega0 LT 0.0) OR (omega0 GT 360.0) ) then $
  689.             omega0 = 64.0
  690.     endif else begin
  691.         omega0 = 64.0
  692.     endelse
  693.  
  694.     ;  Argument of perigee (in degrees).
  695.     ;
  696.     if (N_ELEMENTS(w0) NE 0) then begin
  697.         w0 = FLOAT(w0)
  698.         if ( (w0 LT 0.0) OR (w0 GT 360.0) ) then $
  699.             w0 = 28.0
  700.     endif else begin
  701.         w0 = 28.0
  702.     endelse
  703.  
  704.     ;  Orbit selection
  705.     ;
  706.     ;  1 = circular orbit
  707.     ;  2 = elliptical orbit (default)
  708.     ;  3 = polar orbit
  709.     ;
  710.     if (N_ELEMENTS(select) NE 0) then begin
  711.         if (select EQ 1) then begin
  712.             a = 9200000.0d0
  713.             e = 0.0
  714.             i = 85.0
  715.             M0 = 38.0
  716.             omega0 = 90.0
  717.             w0 = 28.0
  718.         endif else if (select EQ 3) then begin
  719.             a = 9200000.0d0
  720.             e = 0.3
  721.             i = 90.0
  722.             M0 = 0.0
  723.             omega0 = 180.0d0
  724.             w0 = 90.0
  725.         endif else begin
  726.             a = 9200000.0d0
  727.             e = 0.3
  728.             i = 75.0
  729.             M0 = 38.0
  730.             omega0 = 64.0
  731.             w0 = 28.0
  732.         endelse
  733.     endif
  734.  
  735.     ;  Get the current color vectors to restore
  736.     ;  when this application is exited.
  737.     TVLCT, savedR, savedG, savedB, /GET
  738.  
  739.     ; Build color table from color vectors
  740.     ;
  741.     colorTable = [[savedR],[savedG],[savedB]]
  742.  
  743.     ;  Set up dimensions of the drawing (viewing) area.
  744.     ;
  745.     DEVICE, GET_SCREEN_SIZE=screenSize
  746.     xdim = screenSize(0)*0.6
  747.     ydim = xdim*0.8
  748.  
  749.     ;  Get the tips.
  750.     ;
  751.     sText = getTips(filepath('orbit.tip', $
  752.         SUBDIR=['examples','demo', 'demotext']) )
  753.  
  754.     ;  Create widgets.
  755.     ;
  756.     if (N_ELEMENTS(group) NE 0) then begin
  757.         wTopBase = WIDGET_BASE(/COLUMN, $
  758.             TLB_FRAME_ATTR=1, MBAR=barBase, $
  759.             GROUP_LEADER=group, $
  760.             XPAD=0, YPAD=0, $
  761.             /TLB_KILL_REQUEST_EVENTS, $
  762.             TITLE="Orbiting Satellite")
  763.     endif else begin
  764.         wTopBase = WIDGET_BASE(/COLUMN, $
  765.             TLB_FRAME_ATTR=1, MBAR=barBase, $
  766.             XPAD=0, YPAD=0, $
  767.             /TLB_KILL_REQUEST_EVENTS, $
  768.             TITLE="Orbiting Satellite")
  769.     endelse
  770.  
  771.         ;  Create the menu bar. It contains the file,
  772.         ;  edit, and help buttons.
  773.         ;
  774.         wFileButton = WIDGET_BUTTON(barBase, VALUE = 'File', /MENU)
  775.  
  776.             wQuitButton = WIDGET_BUTTON(wFileButton, VALUE='Quit', $
  777.                 UVALUE='QUIT')
  778.  
  779.         ;  Create the menu bar item help that contains the about button.
  780.         ;
  781.         wHelpMenu = WIDGET_BUTTON(barBase, VALUE='About', $
  782.             /HELP, /MENU)
  783.  
  784.             wAboutButton = WIDGET_BUTTON(wHelpMenu, $
  785.                 VALUE='About Orbiting Satellite', UVALUE='ABOUT')
  786.  
  787.  
  788.         ;  Create a sub base of the top base (wBase).
  789.         ;
  790.         wSubBase = WIDGET_BASE(wTopBase, COLUMN=2)
  791.  
  792.             ;  Create the left Base that contains the functionality buttons.
  793.             ;  Here the only button is to animate the object.
  794.             ;
  795.             wLeftbase = WIDGET_BASE(wSubBase,/BASE_ALIGN_CENTER, $
  796.                 COLUMN=1)
  797.  
  798.                 wAnimationBase = WIDGET_BASE(wLeftBase, $
  799.                     /COLUMN, YPAD=10)
  800.  
  801.                     wAnimationLabel = WIDGET_LABEL(wAnimationBase, $
  802.                         VALUE='Animation')
  803.  
  804.                     wStartButton = WIDGET_BUTTON(wAnimationBase, $
  805.                         VALUE="Start", UVALUE='START')
  806.  
  807.                     wStopButton = WIDGET_BUTTON(wAnimationBase, $
  808.                         VALUE="Stop", UVALUE='STOP')
  809.  
  810.                     wResetButton = WIDGET_BUTTON(wAnimationBase, $
  811.                         VALUE="Reset", UVALUE='RESET')
  812.  
  813.                 wScalingBase = WIDGET_BASE(wLeftBase, $
  814.                     /COLUMN, YPAD=10)
  815.  
  816.                     wScalingLabel1 = WIDGET_LABEL(wScalingBase, $
  817.                         VALUE='Satellite Scaling')
  818.  
  819.                     percent = 100
  820.                     scalingString = STRING(percent, FORMAT='(f5.1)') + ' %'
  821.  
  822.                     wScalingLabel2 = WIDGET_LABEL(wScalingBase, $
  823.                         VALUE=scalingString)
  824.  
  825.                     wScalingSlider = WIDGET_SLIDER(wScalingBase, $
  826.                         MINIMUM=0, $
  827.                         MAXIMUM=50, VALUE=25, $
  828.                         /SUPPRESS_VALUE, $
  829.                         UVALUE='SCALING')
  830.  
  831.  
  832.                 wStepBase = WIDGET_BASE(wLeftBase, $
  833.                     /COLUMN, YPAD=10)
  834.  
  835.                     wStepLabel1 = WIDGET_LABEL(wStepBase, $
  836.                         VALUE='Animation Step')
  837.  
  838.                     wStepLabel2 = WIDGET_LABEL(wStepBase, $
  839.                         VALUE='in Seconds')
  840.  
  841.                     wStepSlider = WIDGET_SLIDER(wStepBase, $
  842.                         MINIMUM=25, $
  843.                         MAXIMUM=100, VALUE=50, $
  844.                         UVALUE='STEP')
  845.  
  846.             ;  Create the right Base that has the drawing area.
  847.             ;
  848.             wRightbase = WIDGET_BASE(wSubBase, COLUMN=1, $
  849.                 UVALUE='TIMER')
  850.  
  851.                 wDraw = WIDGET_DRAW(wRightBase, $
  852.                     GRAPHICS_LEVEL=2, $
  853.                     XSIZE=xdim, YSIZE=ydim, /BUTTON_EVENTS, $
  854.                     UVALUE='DRAWING', RETAIN=0, /EXPOSE_EVENT)
  855.  
  856.         ;  Create tips texts.
  857.         ;
  858.         wStatusBase = WIDGET_BASE(wTopBase, MAP=0, /ROW)
  859.  
  860.             nWidgets = 2
  861.             wText = LONARR(nWidgets)
  862.             widTips, wStatusBase, sText.text, XSIZE=36, $
  863.                 YSIZE=3, NWIDGETS=nWidgets, wText
  864.  
  865.     ;  Now the widget have been created, realize it.
  866.     ;
  867.     WIDGET_CONTROL, wTopBase, /REALIZE
  868.  
  869.     ; Returns the top level base to the APPTLB keyword.
  870.     ;
  871.     appTLB = wtopBase
  872.  
  873.     ;  Size the tips widgets.
  874.     ;
  875.     sizeTips, wTopBase, wText, wStatusBase
  876.  
  877.  
  878.     WIDGET_CONTROL, wTopBase, SENSITIVE=0
  879.  
  880.     ;  Grab the window id of the drawable.
  881.     ;
  882.     WIDGET_CONTROL, wDraw, GET_VALUE=oWindow
  883.  
  884.     ;  Compute viewplane rectangle based on aspect ratio.
  885.     ;
  886.     aspect = float(xdim)/float(ydim)
  887.     myview = [-1.0,-1.0,2.0,2.0]
  888.     myview = [-1.5,-1.5,3.0,3.0]
  889.     if (aspect > 1) then begin
  890.         myview(0) = myview(0) - ((aspect-1.0)*myview(2))/2.0
  891.         myview(2) = myview(2) * aspect
  892.     endif else begin
  893.         myview(1) = myview(1) - (((1.0/aspect)-1.0)*myview(3))/2.0
  894.         myview(3) = myview(3) * aspect
  895.     endelse
  896.  
  897.     ; Create view object.
  898.     ;
  899.     oView = OBJ_NEW('idlgrview', PROJECTION=2, EYE=4, $
  900.         ZCLIP=[2.0,-2.0], VIEW=myview, COLOR=[0, 0, 0])
  901.  
  902.     ;  Create a centered starting up text.
  903.     ;
  904.     textLocation = [myview[0]+0.5*myview[2], myview[1]+0.5*myview[3]]
  905.  
  906.     ;  Create and display the PLEASE WAIT text.
  907.     ;
  908.     oFont = OBJ_NEW('IDLgrFont', 'Helvetica', SIZE=18)
  909.     oText = OBJ_NEW('IDLgrText', $
  910.         'Starting up  Please wait...', $
  911.         ALIGN=0.5, $
  912.         LOCATION=textLocation, $
  913.         COLOR=[255,255,0], FONT=oFont)
  914.  
  915.  
  916.     ; Create models and its tre structure.
  917.     ;
  918.     oTopModel = obj_new('idlgrmodel')
  919.         oEarthModel = OBJ_NEW('idlgrmodel')
  920.         oEarthRotationModel = OBJ_NEW('idlgrmodel')
  921.         oEarthScalingModel = OBJ_NEW('idlgrmodel')
  922.         oSatModel = OBJ_NEW('idlgrmodel')
  923.         oSatRotationModel = OBJ_NEW('idlgrmodel')
  924.         oSatScalingModel = OBJ_NEW('idlgrmodel')
  925.  
  926.     ;  Place the model in the view.
  927.     ;
  928.     oView->Add, oTopModel
  929.  
  930.     oTopModel->Add, oText
  931.     oWindow->Draw, oView
  932.  
  933.     oTopModel->Add, oEarthModel
  934.     oTopModel->Add, oSatModel
  935.     oEarthModel->Add, oEarthRotationModel
  936.     oEarthRotationModel->Add, oEarthScalingModel
  937.     oSatModel->Add, oSatRotationModel
  938.     oSatRotationModel->Add, oSatScalingModel
  939.     scale = 2.0
  940.     oEarthScalingModel->Scale, scale, scale, scale
  941.  
  942.     ;  Scale the top model to fit the viewing area.
  943.     ;
  944.     sct = 0.7
  945.     oTopModel->Scale, sct, sct, sct
  946.  
  947.     ;  Create lights
  948.     ;
  949.     oLIght1 = OBJ_NEW('IDLgrLight', DIRECTION=[2, 2, 5], $
  950.         TYPE=2, INTENSITY=0.25)
  951.  
  952.     oLIght2 = OBJ_NEW('IDLgrLight', $
  953.         TYPE=0, INTENSITY=0.7)
  954.  
  955.     oTopModel->Add, oLight1
  956.     oTopModel->Add, oLight2
  957.  
  958.     ;  Create the earth
  959.     ;
  960.     oImageArray = OBJARR(2)
  961.     READ_JPEG, filepath("earth.jpg", $
  962.         SUBDIR=['examples','demo','demodata']), $
  963.         image, TRUE=1
  964.     oImageArray(0) = OBJ_NEW('IDLgrImage', image, HIDE=1)
  965.     READ_JPEG, filepath("cloud.jpg", $
  966.         SUBDIR=['examples','demo','demodata']), $
  967.         image2, TRUE=1
  968.     sizeImage = SIZE(image2)
  969.     rgba = BYTARR(4, sizeImage(2), sizeImage(3))
  970.     rgba(0, *, *) = image2(0, *, *)
  971.     rgba(1, *, *) = image2(1, *, *)
  972.     rgba(2, *, *) = image2(2, *, *)
  973.     rgba(3, *, *) = (FLOAT(image2(0, *, *)) $
  974.         + FLOAT(image2(1, *, *)) + FLOAT(image2(2, *, *)) )/3.0
  975.     oImageArray(1) = OBJ_NEW('IDLgrImage', rgba, HIDE=1)
  976.  
  977.     oEarthScalingModel->Add, oImageArray(0)
  978.     oEarthScalingModel->Add, oImageArray(1)
  979.  
  980.     oSky = OBJ_NEW('orb', COLOR=[255, 255, 255], RADIUS=0.26, $
  981.         DENSITY=0.8, /TEX_COORDS, TEXTURE_MAP=oImageArray(1))
  982.  
  983.     oPlanet = OBJ_NEW('orb', COLOR=[255, 255, 255], RADIUS=0.25, $
  984.         DENSITY=0.8, /TEX_COORDS, TEXTURE_MAP=oImageArray(0))
  985.  
  986.     oEarthScalingModel->Add, oPlanet
  987.     oEarthScalingModel->Add, oSky
  988.     oEarthRotationModel->Rotate, [1,0,0], 90
  989.     oEarthRotationModel->Rotate, [0,1,0], 90
  990.     oEarthRotationModel->GetProperty, TRANSFORM=initEarthTM
  991.     oSatRotationModel->GetProperty, TRANSFORM=initSatTM
  992.     oTopModel->GetProperty, TRANSFORM=initTopTM
  993.  
  994.     ;  Invert texture coordinates.
  995.     ;
  996.     oPlanet->GetProperty, POBJ=p
  997.     p->GetProperty, TEXTURE_COORD=t
  998.  
  999.     t(0,*) = 1.0 - t(0,*)
  1000.     p->SetProperty, TEXTURE_COORD=t
  1001.  
  1002.     oWindow->SetProperty, QUALITY=2
  1003.  
  1004.     ;  Create a satellite object placed into a model,
  1005.     ;  return that model.
  1006.     ;
  1007.     oSatelliteModel = CreateSatellite()
  1008.     oSatScalingModel->Add, oSatelliteModel
  1009.  
  1010.     ;  Initialize the Keplerian orbit elements
  1011.     ;  at the epoch time here
  1012.     ;
  1013. ;    a =  9000000.0     ; semi-major axis in meters
  1014. ;    e = 0.0            ; eccentricity (dimensionless)
  1015. ;    i =  80.0          ; inclination in degrees
  1016. ;    M0 =  38.0         ; mean anomaly at the epoch time (degree)
  1017. ;    omega0 = 90.0     ; Longitude of ascending node at the epoch (degree)
  1018. ;    w0 = 28.0          ; argument of perigee (degree)
  1019.  
  1020.     rad = !DPI / 180.0
  1021.     sini = sin(i * rad)
  1022.     cosi = cos(i * rad)
  1023.  
  1024.     ;  Compute the secular orbit perturbations due to J2.
  1025.     ;
  1026.     J2 = 1.0822d-3
  1027.     u = 3.9860044d14
  1028.     n = SQRT(u / a^3)
  1029.     kterm = 3.0*n * J2 / $
  1030.         (2.0* a * a * (1.0 - e*e)^2)
  1031.     dwdt = -kterm * ( 2.5*sini^2 -2.0 )
  1032.     dOmegadt = -kterm * cosi
  1033.     dMdt = n - kterm * SQRT(1.0 - e*e) * $
  1034.         ( 1.5*sini^2 - 1.0 )
  1035.  
  1036.     ;  Place the orbital elements and the secular rate due to J2
  1037.     ;  into a structure.
  1038.     ;
  1039.     sOrbit = { $
  1040.         A: a, $                        ; orbital elements , semi-major axis
  1041.         E: e, $                        ; eccentricity
  1042.         i: i, $                        ; inclination
  1043.         M0:m0, $                       ; mean anomaly
  1044.         Omega0: omega0, $              ; longitude of ascending node
  1045.         w0: w0, $                      ; argument of perigee
  1046.         DMdt: dMdt, $                  ; secular rate due to J2: mean anomaly
  1047.         dOmegadt: dOmegadt, $          ; longitude of ascending node
  1048.         dwdt: dwdt $                   ; argument of perigee
  1049.     }
  1050.  
  1051.     ;  Translate the satellite and place it to its
  1052.     ;  location at the epoch time
  1053.     ;
  1054.     position = FindPosition(sOrbit, 0.0d0)
  1055.     newPosition = position/6378137.0
  1056.  
  1057.     ;  The orbit coordinate system does not correspond to
  1058.     ;  the graphic coordinates system. The linear transformation
  1059.     ;  is done by translating the satellite (oSatModel) as
  1060.     ;  follows :
  1061.     ;    orbit coord. system    graphic coord. system
  1062.     ;         x                      z
  1063.     ;         y                      x
  1064.     ;         z                      y
  1065.     ;
  1066.     oSatModel->Translate, newPosition(1), newPosition(2), newPosition(0)
  1067.  
  1068.     ;  Add the trackball object for interactive change
  1069.     ;  of the scene orientation
  1070.     ;
  1071.     oTrack = OBJ_NEW('Trackball', [xdim/2.0, ydim/2.0], xdim/2.0)
  1072.  
  1073.     ocontainer = OBJ_NEW('IDLgrContainer')
  1074.     oContainer->Add, oView
  1075.     oContainer->Add, oTrack
  1076.  
  1077.     sState = { $
  1078.         ColorTable: colorTable, $            ; Color table to restore
  1079.         Btndown:0b, $                        ; 0= not presses, pressed otherwise
  1080.         SOrbit: SOrbit, $                    ; Orbital elements structure
  1081.         InitEarthTM: initEarthTM, $          ; Initial Orientation of Earth
  1082.         InitSatTM: initSatTM, $              ; Initial Satellite transformation
  1083.         InitTopTM: initTopTM, $              ; Initial transformationo of top model
  1084.         InitSatPosition: newPosition, $      ; Initial Position of the satellite
  1085.         StopFlag: 0, $                       ; 0= animation not stopped, 1=stopped
  1086.         Position: newPosition, $             ; Updated position of the satellite
  1087.         Timer: 0.1, $                        ; Time delay between frame
  1088.         Time: 0.00d0, $                      ; Accumulated time (sec.)
  1089.         TimeIncrement: 50.0, $               ; Time between frames (sec.)
  1090.         SkyAngle: 0.0, $                     ; rotation angle of the clouds (sky)
  1091.         WTopBase: wTopBase, $                ; Top level base IDs
  1092.         WRightBase: wRightBase, $            ; Right base ID
  1093.         WStartButton: wStartButton, $        ; Animation buttons IDs
  1094.         WResetButton: wResetButton, $
  1095.         WStopButton: wStopButton, $
  1096.         WScalingSlider: wScalingSlider, $    ; Sliders IDs
  1097.         WScalingLabel2: wScalingLabel2, $    ; Sliders IDs
  1098.         WStepSlider: wStepSlider, $
  1099.         WDraw: wDraw, $                      ; Wdiget draw ID
  1100.         OView: oView, $                      ; View object
  1101.         OWindow: oWindow, $                  ; Window object
  1102.         OSatModel: oSatModel, $              ; Satellite models
  1103.         OSatRotationModel: oSatRotationModel, $
  1104.         OSatScalingModel: oSatScalingModel, $
  1105.         OEarthRotationModel: oEarthRotationModel, $ ; Earth models
  1106.         OSky: oSky, $                        ; Clouds image object
  1107.         OTrack: oTrack, $                    ; Trackball object
  1108.         OFont: oFont, $                      ; Font object
  1109.         OText: oText, $                      ; Text object
  1110.         OContainer: oContainer, $            ; Container object
  1111.         OTopModel:oTopModel, $               ; Top model
  1112.         groupBase: groupBase $               ; Base of Group Leader
  1113.     }     
  1114.  
  1115.     WIDGET_CONTROL, wTopBase, SET_UVALUE=sState, /NO_COPY
  1116.  
  1117.     WIDGET_CONTROL, wStartButton, SENSITIVE=0
  1118.     WIDGET_CONTROL, wResetButton, SENSITIVE=0
  1119.  
  1120.     ;  Draw the first view.
  1121.     ;
  1122.     WIDGET_CONTROL, wTopBase, /HOURGLASS
  1123.     oTopModel->Remove, oText
  1124.     oWindow->Draw, oView
  1125.     
  1126.     WIDGET_CONTROL, wTopBase, SENSITIVE=1
  1127.  
  1128.     ;  Animate at start up.
  1129.     ;
  1130.     pseudoEvent = { $
  1131.        ID: wRightBase, $
  1132.        TOP: wTopBase, $
  1133.        HANDLER: wTopBase $
  1134.     }
  1135.  
  1136.     d_orbit_event, pseudoEvent
  1137.  
  1138.     XMANAGER, 'd_orbit', wTopBase, EVENT_HANDLER='d_orbit_event', $
  1139.         /NO_BLOCK, $
  1140.         CLEANUP='D_Orbit_Cleanup'
  1141.  
  1142. end
  1143.